package com.ml.doctor.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;

import com.ml.doctor.R;


/**
 * Created by damon on 15/7/16.
 */
public class TableView extends LinearLayout implements View.OnClickListener {

    private Paint mPaint;
    private OnItemClickListener mClickListener;
    private BaseAdapter adapter;
    private int dividerColor;
    private int dividerColorOfGroup;
    private boolean dividerOfTopEnable;
    private boolean dividerOfGroupEnable;
    private boolean dividerEnable;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what != 1) return;
            if (adapter == null || adapter.isEmpty()) {
                removeAllViews();
                return;
            }
            removeAllViews();
            for (int i = 0; i < adapter.getCount(); i++) {
                View view = adapter.getView(i, null, TableView.this);
                if (view != null) {
                    addView(view);
                }
            }
        }
    };

    public TableView(Context context) {
        this(context, null);
    }

    public TableView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TableView);
        dividerColor = array.getColor(R.styleable.TableView_divider_color, 0xffe1e1e1);
        dividerColorOfGroup = array.getColor(R.styleable.TableView_group_divider_color, 0xffe1e1e1);
        dividerOfTopEnable = array.getBoolean(R.styleable.TableView_top_divider_enable, false);
        dividerOfGroupEnable = array.getBoolean(R.styleable.TableView_group_divider_enable, false);
        dividerEnable = array.getBoolean(R.styleable.TableView_divider_enable, true);
        array.recycle();

        setOrientation(VERTICAL);

        mPaint = new Paint();
    }

    public void setDividerColor(int color) {
        if (dividerColor == color) {
            return;
        }
        this.dividerColor = color;
        requestLayout();
    }

    public void setDividerOfTopEnable(boolean enable) {
        if (dividerOfTopEnable == enable) {
            return;
        }
        this.dividerOfTopEnable = enable;
        requestLayout();
    }

    public void setDividerOfGroupEnable(boolean enable) {
        if (dividerOfGroupEnable == enable) {
            return;
        }
        this.dividerOfGroupEnable = enable;
        requestLayout();
    }

    public void setDividerColorOfGroup(int color) {
        if (dividerColorOfGroup == color) {
            return;
        }
        this.dividerColorOfGroup = color;
        requestLayout();
    }

    public void setDividerEnable(boolean dividerEnable) {
        if (this.dividerEnable == dividerEnable) {
            return;
        }
        this.dividerEnable = dividerEnable;
        requestLayout();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        int k = 0;
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child != null && child.getVisibility() == View.VISIBLE && !(child instanceof TableHeader) && child.getHeight() > 0) {
                if (k == 0) {
                    drawTopLine(canvas, child);
                }
                if (isGroupEnd(i)) {
                    drawDividerOfGroupEnd(canvas, child);
                } else {
                    drawDivider(canvas, child);
                }
                k++;
            }
        }
    }

    private boolean isGroupEnd(int pos) {
        for (int i = pos + 1; i < getChildCount(); i++) {
            View v = getChildAt(i);
            if (v != null && v.getVisibility() == VISIBLE) {
                return v instanceof TableHeader;
            }
        }
        return true;
    }

    private void drawDivider(Canvas canvas, View view) {
        if (!dividerEnable) {
            return;
        }
        mPaint.setColor(dividerColor);
        mPaint.setStrokeWidth(1.0f);
        final Rect bounds = new Rect();
        bounds.left = getPaddingLeft() + getItemPadding();
        bounds.top = view.getBottom();
        bounds.right = getRight() - getLeft() - getPaddingRight();
        canvas.drawLine(bounds.left, bounds.top, bounds.right, bounds.top, mPaint);
    }

    private int itemPadding = getResources().getDimensionPixelOffset(R.dimen.table_item_padding);

    public void setItemPadding(int padding) {
        itemPadding = padding;
    }

    private int getItemPadding() {
        return itemPadding;
    }

    private void drawDividerOfGroupEnd(Canvas canvas, View view) {
        if (!dividerOfGroupEnable) {
            return;
        }
        int color = this.dividerColorOfGroup > 0 ? this.dividerColorOfGroup : this.dividerColor;
        mPaint.setColor(color);
        mPaint.setStrokeWidth(1.0f);
        final Rect bounds = new Rect();
        bounds.left = getPaddingLeft();
        bounds.top = view.getBottom() - 1;
        bounds.right = getRight() - getLeft() - getPaddingRight();
        canvas.drawLine(bounds.left, bounds.top, bounds.right, bounds.top, mPaint);
    }

    private void drawTopLine(Canvas canvas, View view) {
        if (!dividerOfTopEnable) {
            return;
        }
        mPaint.setColor(dividerColor);
        mPaint.setStrokeWidth(1.0f);
        Rect bounds = new Rect();
        bounds.left = getPaddingLeft();
        bounds.top = view.getTop();
        bounds.right = getRight() - getLeft() - getPaddingRight();
        canvas.drawLine(bounds.left, bounds.top, bounds.right, bounds.top, mPaint);
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        mClickListener = listener;
    }

    private final DataSetObserver observer = new DataSetObserver() {
        @Override
        public void onChanged() {
            handler.removeMessages(1);
            handler.sendEmptyMessageDelayed(1, 100);
        }

        @Override
        public void onInvalidated() {
            onChanged();
        }
    };

    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        handler.removeCallbacksAndMessages(null);
    }

    public BaseAdapter getAdapter() {
        return adapter;
    }

    public void setAdapter(BaseAdapter adapter) {
        if (this.adapter != null) this.adapter.unregisterDataSetObserver(observer);
        this.adapter = adapter;
        if (this.adapter != null) this.adapter.registerDataSetObserver(observer);
        removeAllViews();
        observer.onChanged();
    }

    @Override
    public void onClick(View v) {
        if (mClickListener != null) {
            int position = -1;
            long id = -1;
            for (int i = 0; i < getChildCount(); i++) {
                View view = getChildAt(i);
                if (v == view) {
                    position = i;
                    break;
                }
            }
            if (position < 0) return;
            if (adapter != null) id = adapter.getItemId(position);
            if (id == -1) {
                id = v.getId();
            }
            mClickListener.onItemClick(this, v, position, id);
        }
    }

    public interface OnItemClickListener {
        void onItemClick(TableView parent, View view, int position, long id);
    }

    public Object getItemAtPosition(int position) {
        return (adapter == null || position < 0) ? null : adapter.getItem(position);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child != null && child.getVisibility() == View.VISIBLE && !(child instanceof AdapterView)) {
                if (mClickListener != null) {
                    boolean isClickable = child.isClickable();
                    child.setOnClickListener(this);
                    if (!isClickable) child.setClickable(false);
                }
            }
        }
    }
}
